# 从K线区读取当天公告

import cv2
import logging
from PIL import ImageGrab
import numpy as np
import pyautogui
import time
from shape_judgment.screen_region_storage import get_region,get_region_pos_only

# # 窗口偏移位置
# window_pos = (0,0) # 实时获取就行
# K线区域的相对坐标:
# k_line_area_pos = (0,0) # 去其它模块获取, 而不是增加上层调用的冗余
# def set_window_pos(x,y):
#     global window_pos
#     window_pos = (x,y)
# def set_k_line_area_pos(x,y):
#     global k_line_area_pos
#     k_line_area_pos = (x,y)

class read_bulletin_board:
    # 构造造函数:
    def __init__(self,window):
        self.efortune_window = window        
        x, y = self.efortune_window.left, self.efortune_window.top
        width, height = self.efortune_window.width, self.efortune_window.height
        self.window_pos = (x, y, width, height) # 窗口偏移位置
        self.template_dividend = cv2.imread("eastmoney desktop software picture/k_dividend_rights_implementation_announcement.png")


    def capture_window(self):
        try:
            # 获取窗口位置和大小
            x, y ,width, height = self.window_pos
            # 截取窗口区域
            screenshot = ImageGrab.grab(bbox=(x, y, x + width, y + height))
            # 转换为OpenCV格式 (BGR)
            self.frame = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
        except Exception as e:
            logging.error(f"!!!! ERR 36 F10截图时出错: {str(e)}")
            raise Exception(f"!!!! ERR 36 F10截图时出错: {str(e)}")
            return None
    
        # 找 模板匹配
    def find_template(self,screen_img, template_img, threshold=0.85):
    	# 找到了, 就返回True

        if screen_img is None:return False
        
        """获取所有符合阈值的匹配结果，返回列表[(x, y, w, h, 匹配度)]"""
        # # 预处理（使用之前优化的预处理函数）
        h, w = template_img.shape[:2]
        
        if h == 0 or w == 0:
            raise Exception("!!!! ERR 58 模板尺寸为零")
        
        if screen_img.size < template_img.size:  # 截图尺寸小于模板尺寸
            cv2.imwrite('bulletin_board_find_template.png', screen_img)
            # print("截图尺寸小于模板尺寸")
            raise Exception(f"!!!!    ERR 58 截图尺寸小于模板尺寸 截图size:{screen_img.size}")
        
        # 执行模板匹配并获取匹配度矩阵
        result = cv2.matchTemplate(
            screen_img, 
            template_img, 
            cv2.TM_CCOEFF_NORMED
        )
        # 找到所有超过阈值的位置
        locations = np.where(result >= threshold)
        all_matches = []
        
        # 遍历所有匹配位置，记录坐标和匹配度
        for y, x in zip(locations[0], locations[1]):
            match_value = result[y, x]  # 该位置的匹配度（0-1）
            all_matches.append((x, y, w, h, match_value))  # 存储x坐标、y坐标、宽、高、匹配度
            # print(f"# 74 {(x, y, w, h, match_value)}")
        return 0 != len(all_matches)
    
    # 鼠标悬停
    def mouse_hovering(self):
        # [k_x, k_y,k_width, k_height] = self.k_line_area_pos
        k_x_1,k_x_2,k_y_1,k_y_2 = self.k_line_area_pos # (x1,x2,y1,y2)        
        target_x = k_x_2-6 + self.window_pos[0]
        target_y = k_y_1+7 + self.window_pos[1]
        # 移动鼠标:
        pyautogui.moveTo(target_x, target_y, duration=1.5)
        # 等信息出现:
        time.sleep(1.0) # 1秒不保险

    # 移开鼠标以免挡住其它功能
    def mouse_move_away(self):
        target_x = self.window_pos[0] + self.window_pos[2]
        target_y = self.window_pos[1] + self.window_pos[3]
        pyautogui.moveTo(target_x, target_y, duration=0.0)

    # 判断子窗口已经出现:
    def is_child_window_already_appeared(self):
        # 算出目前的鼠标位置:
        k_x_1,k_x_2,k_y_1,k_y_2  = self.k_line_area_pos # (x1,x2,y1,y2)
        mouse_x = k_x_2-6
        mouse_y = k_y_1+7

        point_left=(0,0)
        point_right=(0,0)
        print_top=(0,0)
        print_bottom=(0,0)

        # 取当前像素点:
        color_current = self.frame[mouse_y,mouse_x]
        if 0 == color_current[0]:
            print("# 71 已经出现子窗口")
            self.frame[mouse_y,mouse_x] = (0,0,255)
            cv2.imwrite('bulletin_board_area_sub_window.png', self.frame)
            raise Exception("# 79 鼠标就在边框上")

        # BEGIN 从鼠标位置向左找, 找一个全黑的像素
        delta = 1
        current_pos_x,current_pox_y = (mouse_x-delta,mouse_y)
        while True:
            color_current = self.frame[current_pox_y,current_pos_x]
            if 0 == color_current[0]:
                print("# 80 已经出现子窗口")
                self.frame[current_pox_y,current_pos_x] = (0,255,255)
                self.frame[mouse_y,mouse_x] = (0,0,255)
                print(f"pos mouse:{mouse_x,mouse_y} \t pos border:{current_pos_x,current_pox_y}")
                point_left = current_pos_x
                break
            delta+=1
            current_pos_x,current_pox_y = (mouse_x-delta,mouse_y)
            if(current_pos_x <=0 ):break
        # END  从鼠标位置向左找, 找一个全黑的像素

        # BEGIN 从鼠标位置向右找, 找一个全黑的像素
        # 这里需要处理过宽的情况, 有时子窗口是伸出主窗口右边界的, 判断如果到了主窗口边界,就算是找到边界
        delta = 1
        current_pos_x,current_pox_y = (mouse_x+delta,mouse_y)
        while True:
            color_current = self.frame[current_pox_y,current_pos_x]
            if 0 == color_current[0]:
                print("# 95 已经出现子窗口")
                self.frame[current_pox_y,current_pos_x] = (0,255,255)
                self.frame[mouse_y,mouse_x] = (0,0,255)
                print(f"# 101 {self.frame[current_pox_y,current_pos_x]}")
                print(f"# 102 {self.frame[mouse_y,mouse_x]}")
                print(f"pos mouse:{mouse_x,mouse_y} \t pos border:{current_pos_x,current_pox_y}")
                point_right = current_pos_x
                break
            delta+=1
            current_pos_x,current_pox_y = (mouse_x+delta,mouse_y)
            if(current_pos_x >=self.window_pos[2]-1):break
        if (0,0) == point_right:
            point_right = self.window_pos[2]-1
        # END  从鼠标位置向右找, 找一个全黑的像素

        # BEGIN 从鼠标位置向上找, 找一个全黑的像素
        delta = 1
        current_pos_x,current_pox_y = (mouse_x,mouse_y-delta)
        while True:
            color_current = self.frame[current_pox_y,current_pos_x]
            if 0 == color_current[0]:
                print("# 110 已经出现子窗口")
                self.frame[current_pox_y,current_pos_x] = (0,255,255)
                self.frame[mouse_y,mouse_x] = (0,0,255)
                print_top = current_pox_y
                break
            delta+=1
            current_pos_x,current_pox_y = (mouse_x,mouse_y-delta)
            if(current_pox_y <=0):break
        # END  从鼠标位置向上找, 找一个全黑的像素

        # BEGIN 从鼠标位置向下找, 找一个全黑的像素
        delta = 1
        current_pos_x,current_pox_y = (mouse_x,mouse_y+delta)
        while True:
            color_current = self.frame[current_pox_y,current_pos_x]
            if 0 == color_current[0]:
                print("# 125 已经出现子窗口")
                self.frame[current_pox_y,current_pos_x] = (0,255,255)
                self.frame[mouse_y,mouse_x] = (0,0,255)
                print_bottom = current_pox_y
                break
            delta+=1
            current_pos_x,current_pox_y = (mouse_x,mouse_y+delta)
            if(current_pox_y >=self.window_pos[3]):break
        # END  从鼠标位置向下找, 找一个全黑的像素
        
        # # BEGIN Debug: 
        # cv2.imwrite('bulletin_board_area_sub_window.png', self.frame)
        # if not ( (0,0) == print_top or (0,0) == print_bottom or (0,0) == point_left ):
        #     cv2.imwrite('bulletin_board_area_sub_window_2.png', self.frame[print_top+1:print_bottom,point_left+1:point_right])
        # # END Debug

        if (0,0) == print_top or (0,0) == print_bottom or (0,0) == point_left:return None
        return self.frame[print_top+1:print_bottom,point_left+1:point_right]
        print(f"# 151 point_left:{point_left} \t point_right:{point_right} \t print_top:{print_top} \t print_bottom:{print_bottom}")
        cv2.imwrite('bulletin_board_area_sub_window_2.png', self.frame[print_top+1:print_bottom,point_left+1:point_right])
        return (point_left,point_right,print_top,print_bottom)




    # @ return 有分红公告
    def read_bulletin_board_in_k_line_area(self,screen_shot_k_line_chat):
        print("# 6 BEGIN read_bulletin_board_in_k_line_area")
        img_bulletin_board_area = screen_shot_k_line_chat[0:7,-7:]
        cv2.imwrite('bulletin_board_area_8.png', img_bulletin_board_area)# 调试结果是正确的

        # 判断当天有公告
        key_color = img_bulletin_board_area[-1,0]
        key_b,key_g,key_r = key_color
        print("# 12 key_color:", key_color)
        if (76,76,76) == (key_b,key_g,key_r) or (192,192,192) == (key_b,key_g,key_r):        
            # 如果是十字线, 是139,139,139, 被十字线覆盖时是76,76,76, 没被覆盖时是192,192,192
            print("# 14 有")
            # 把初始化移出构造函数, 不然会在构造函数中崩溃, 但又必须在鼠标移动前做出坐标的获取
            self.k_line_area_pos = get_region("K线图表区") # K线区域的相对坐标 (x1,x2,y1,y2)

            img_subwindow_appeared = None
            while img_subwindow_appeared is None:
                self.mouse_hovering()
                # 截图
                self.capture_window() # BUG: 到这一步时, 发现当天没公告, 就会卡死.
                # 读取截图, 判断是否出现了子窗口
                img_subwindow_appeared = self.is_child_window_already_appeared()
                if img_subwindow_appeared is None:
                    # 截取出 k_line_chat 以再判断一次有没有公告, 避免卡死
                    x1,x2,y1,y2 = self.k_line_area_pos
                    screen_shot_k_line_chat = self.frame[y1:y2,x1:x2]
                    img_bulletin_board_area = screen_shot_k_line_chat[0:7,-7:]
                    key_color = img_bulletin_board_area[-1,0]
                    key_b,key_g,key_r = key_color
                    if not ( (76,76,76) == (key_b,key_g,key_r) or (192,192,192) == (key_b,key_g,key_r)) :
                        logging.info("# 230 read_bulletin_board  避免卡死")
                        break # 避免卡死
                # 处理完后移开鼠标 # 移开再进入, 才能触发悬停事件
                self.mouse_move_away()
            self.mouse_move_away()
            bool_is_match = False
            if img_subwindow_appeared is not None:
                bool_is_match = self.find_template(img_subwindow_appeared,self.template_dividend)
            return bool_is_match

            # print(f"bool_subwindow_appeared:{bool_subwindow_appeared}")


            raise Exception("有公告 开发中的中断")
        else:
            return None
        

        print("# 10 END read_bulletin_board_in_k_line_area")
        return None


#[MISSION]取上方的公告区
#	背景色一定是7,7,7 , 公告图标一定是192,192,192
#	当天的公告图标中心点: w:-7 h:7
#	[M]建个模块来处理这个 
#		现在纠结一个问题是: 需要等一下才刷新出新的数据, 至于什么时候刷出来,不清楚
#		一般, 刷新出图表区后, 才会刷新出右侧的红绿数字. 那这还得等右边的解析模块出来后再做, 现在先做出能做的.
#		

# 2025-10-30
# 鼠标悬停的位置, 改到(-6,7) 图标有两种, 一种比较瘦